package com.onenine.app.fragment;

import android.Manifest;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Looper;
import android.os.MessageQueue;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.ImageButton;

import com.onenine.app.R;
import com.onenine.app.activity.DiscoveryExploreActivity;
import com.onenine.app.activity.SendBarrageActivity;
import com.onenine.app.danmu.CacheStufferAdapter;
import com.onenine.app.danmu.DanmuCacheStuffer;
import com.onenine.app.event.BarrageListEvent;
import com.onenine.app.event.TabStyleEvent;
import com.onenine.app.model.BarrageItem;
import com.onenine.app.request.CommonRequest;
import com.onenine.app.response.GetBarragesResponse;
import com.onenine.app.utils.CHelper;
import com.onenine.app.utils.DataType;
import com.onenine.app.utils.RoleResLoader;
import com.onenine.app.utils.UrlConfig;
import com.onenine.app.view.LocalVideoView;
import com.onenine.app.view.popwin.BarrageListPopWindow;
import com.onenine.base.base.BaseEventFragment;
import com.onenine.base.okhttp.OkCallback;
import com.onenine.base.okhttp.OkRequest;
import com.onenine.base.utils.StatusBarUtils;
import com.onenine.base.utils.Toasty;
import com.onenine.chat.rongcloud.RcUser;
import com.onenine.common.util.ActivityUtils;
import com.onenine.common.util.ApUtils;
import com.onenine.common.util.Logger;
import com.onenine.common.util.SizeUtils;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import master.flame.danmaku.controller.DrawHandler;
import master.flame.danmaku.controller.IDanmakuView;
import master.flame.danmaku.danmaku.model.BaseDanMu;
import master.flame.danmaku.danmaku.model.DanmakuTimer;
import master.flame.danmaku.danmaku.model.Duration;
import master.flame.danmaku.danmaku.model.IDanmakus;
import master.flame.danmaku.danmaku.model.IDisplayer;
import master.flame.danmaku.danmaku.model.android.DanmakuContext;
import master.flame.danmaku.danmaku.model.android.Danmakus;
import master.flame.danmaku.danmaku.parser.BaseDanmakuParser;
import master.flame.danmaku.danmaku.util.SystemClock;
import master.flame.danmaku.ui.widget.DanMuView;
import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;

public class DiscoveryFragment extends BaseEventFragment implements View.OnClickListener
        , LocalVideoView.OnLocalCompletionListener, DrawHandler.Callback, IDanmakuView.OnDanmakuClickListener, EasyPermissions.PermissionCallbacks {

    private final String[] PERMISSIONS = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
    private final int RC_PERMISSION = 0x0001;
    private DanMuView mDanmakuView;
    private DanmakuContext mContext;
    private ImageButton mBtnExplore, mBtnBarrage;
    private boolean isBarragePause, isOpenStyleFinish;
    private Random mRandom = new Random();
    private DanmuCacheStuffer mDanmuStuffer;
    private List<BarrageItem> mBarrageList;
    private LocalVideoView mVideoView;
    private ExecutorService mExecutorService = Executors.newFixedThreadPool(1);

    @Override
    protected int getLayout() {
        return R.layout.fragment_discovery;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        setDarkModeStyle();
        StatusBarUtils.setTransparentForImageViewInFragment(getActivity(), null);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void initView(View view) {
        mVideoView = view.findViewById(R.id.vv_view);
        mBtnExplore = view.findViewById(R.id.btn_explore);
        mBtnBarrage = view.findViewById(R.id.btn_barrage);
        mDanmakuView = view.findViewById(R.id.dv_danmu);
        mBtnBarrage.setImageResource(RoleResLoader
                .getRoleDrawableResourceId(RoleResLoader.DynamicResName.BTN_BARRAGE_CREATE));
        mVideoView.startVideo(CHelper.getRawResouceString(R.raw.discovery_open_style), false);
        EventBus.getDefault().post(new TabStyleEvent(true));
    }

    @Override
    protected void initListener() {
        super.initListener();
        mBtnBarrage.setOnClickListener(this);
        mBtnExplore.setOnClickListener(this);
        mVideoView.setLocalCompletionListener(this);
    }

    @Override
    public void initData() {
        super.initData();
        initBarrageConfig();
    }

    /**
     * 初始化弹幕配置
     */
    private void initBarrageConfig() {
        // 设置最大显示行数
        HashMap<Integer, Integer> maxLinesPair = new HashMap<>();
        maxLinesPair.put(BaseDanMu.TYPE_SCROLL_RL, 7); // 滚动弹幕最大显示5行
        // 设置是否禁止重叠
        HashMap<Integer, Boolean> overlappingEnablePair = new HashMap<>();
        overlappingEnablePair.put(BaseDanMu.TYPE_SCROLL_RL, true);
        mDanmuStuffer = new DanmuCacheStuffer(getActivity());
        mContext = DanmakuContext.create();
        mContext.setDanmakuStyle(IDisplayer.DANMAKU_STYLE_STROKEN, 3)
                .setDuplicateMergingEnabled(false)
                .setScrollSpeedFactor(1.5f)
                .setMaximumLines(maxLinesPair)
                .preventOverlapping(overlappingEnablePair).setDanmakuMargin(SizeUtils.dp2px(18))
                .setCacheStuffer(mDanmuStuffer, new CacheStufferAdapter(ApUtils.getApp(), mDanmakuView));
        mDanmakuView.setCallback(this);
        mDanmakuView.setOnDanmakuClickListener(this);
        mDanmakuView.prepare(new BaseDanmakuParser() {

            @Override
            protected Danmakus parse() {
                return new Danmakus();
            }
        }, mContext);
        mDanmakuView.showFPS(false);
        mDanmakuView.enableDanmakuDrawingCache(true);
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        if (hidden) {
            pauseVideoPlay();
            EventBus.getDefault().post(new TabStyleEvent(false));
            StatusBarUtils.setFullScreenLightMode(getActivity());
        } else {
            resumeVideoPlay();
            setDarkModeStyle();
            EventBus.getDefault().post(new TabStyleEvent(true));
            StatusBarUtils.setTransparentForImageViewInFragment(getActivity(), null);
        }
    }

    /**
     * 恢复播放
     */
    private void resumeVideoPlay() {
        if (isOpenStyleFinish) {
            mVideoView.resumeVideo();
        }
    }

    /**
     * 暂停播放
     */
    private void pauseVideoPlay() {
        if (isOpenStyleFinish) {
            mVideoView.pauseVideo();
        }
    }

    /**
     * 设置状态栏白字样式
     */
    private void setDarkModeStyle() {
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
            @Override
            public boolean queueIdle() {
                StatusBarUtils.setDarkMode(getActivity());
                return false;
            }
        });
    }

    /**
     * 拉取弹幕列表
     */
    private void getLatestBarrageData() {
        OkRequest.getInstance().withUrl(UrlConfig.GET_LATEST_BARRAGES)
                .withRequest(new CommonRequest(RcUser.getInstance().getUserId()))
                .doRequest(DiscoveryFragment.class.getSimpleName(), new OkCallback<GetBarragesResponse>() {
                    @Override
                    public void onResponse(final GetBarragesResponse response, String srcData) {
                        if (response.isSuccess()) {
                            mBarrageList = response.getBarrageItems();
                            showBarragesRandom(response.getBarrageItems());
                        }
                    }
                });
    }

    /**
     * 随机性延时添加弹幕
     *
     * @param barrageItems
     */
    private void showBarragesRandom(final List<BarrageItem> barrageItems) {
        try {
            mExecutorService.submit(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < barrageItems.size(); i++) {
                        if (mDanmakuView == null) {
                            Logger.e("弹幕组件被销毁了");
                            break;
                        }
                        if (i == barrageItems.size() - 1 && !isBarragePause) {
                            //弹幕走完再次拉取后台弹幕
                            SystemClock.sleep(1000 / barrageItems.size());
                            EventBus.getDefault().post(new BarrageListEvent(barrageItems));
                        }
                        addImageTextDanMu(barrageItems.get(i));
                        SystemClock.sleep(200 + 2 * mRandom.nextInt(200));
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        resumeVideoPlay();
        if (mDanmakuView.isPrepared() && isBarragePause) {
            mDanmakuView.resume();
            isBarragePause = false;
            getLatestBarrageData();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        pauseVideoPlay();
        if (mDanmakuView.isPrepared()) {
            mDanmakuView.pause();
            isBarragePause = true;
        }
    }

    @Override
    public void updateTimer(DanmakuTimer timer) {
    }

    @Override
    public void drawingFinished() {
    }

    @Override
    public void danmakuShown(BaseDanMu danmaku) {
    }

    @Override
    public void prepared() {
        mDanmakuView.start();
    }

    @Override
    public boolean onDanmakuClick(IDanmakus danmakus) {
        BaseDanMu latest = danmakus.last();
        if (latest != null) {
            BarrageItem item = (BarrageItem) latest.tag;
            item.setTouchClick(true);
            mDanmakuView.invalidateDanmaku(latest, true);
            new BarrageListPopWindow(getActivity()
                    , mBarrageList, item).showPopWindow();
            return true;
        }
        return false;
    }

    @Override
    public boolean onDanmakuLongClick(IDanmakus danmakus) {
        return false;
    }

    @Override
    public boolean onViewClick(IDanmakuView view) {
        return false;
    }

    /**
     * 添加图文弹幕
     *
     * @param barrageItem
     */
    private void addImageTextDanMu(BarrageItem barrageItem) {
        if (barrageItem.getSex() <= 0 || barrageItem.getBarrageType() <= 0
                || barrageItem.getBarrageType() > DataType.BARRAGE_VOICE) {
            Logger.e("该弹幕数据有误");
            return;
        }
        BaseDanMu danmaku = mContext.mDanmakuFactory.createDanmaku(BaseDanMu.TYPE_SCROLL_RL, mContext);
        danmaku.text = "";
        danmaku.padding = SizeUtils.dp2px(10);
        danmaku.priority = 0;  // 一定会显示, 一般用于本机发送的弹幕
        danmaku.isLive = true;
        danmaku.textShadowColor = 0; // 重要：如果有图文混排，最好不要设置描边(设textShadowColor=0)，否则会进行两次复杂的绘制导致运行效率降低
        danmaku.tag = barrageItem;
        if (mRandom.nextBoolean()) {
            danmaku.setDuration(new Duration(4000 + (int) (3000 * mRandom.nextInt(10) / 10f
                    + 0.02 * barrageItem.getContent().length())));
        }
        danmaku.setTime(mDanmakuView.getCurrentTime());
        mDanmakuView.addDanmaku(danmaku);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_barrage) {
            ActivityUtils.startActivity(getActivity(), SendBarrageActivity.class);
        } else if (v.getId() == R.id.btn_explore) {
            checkLocationPermission();
        }
    }

    /**
     * 检查是否开启了定位权限
     */
    private void checkLocationPermission() {
        if (EasyPermissions.hasPermissions(getActivity(), PERMISSIONS)) {
            ActivityUtils.startActivity(getActivity(), DiscoveryExploreActivity.class);
        } else {
            EasyPermissions.requestPermissions(this
                    , getString(R.string.permission_location_hint)
                    , RC_PERMISSION, PERMISSIONS);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        if (requestCode == RC_PERMISSION && perms.size() == PERMISSIONS.length) {
            ActivityUtils.startActivity(getActivity(), DiscoveryExploreActivity.class);
        }
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this)
                    .setTitle(R.string.permission_apply)
                    .setRationale(R.string.explorer_permission_setting_hint)
                    .build().show();
        } else {
            Toasty.showNormal(R.string.explorer_permission_hint);
        }
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        if (!isOpenStyleFinish) {
            isOpenStyleFinish = true;
            mVideoView.startVideo(CHelper.getRawResouceString(R.raw.discovery_anim_style), true);
            getLatestBarrageData();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) {
            if (EasyPermissions.hasPermissions(getActivity(), PERMISSIONS)) {
                ActivityUtils.startActivity(getActivity(), DiscoveryExploreActivity.class);
            } else {
                Toasty.showNormal(R.string.explorer_permission_hint);
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(BarrageItem newBarrageItem) {
        if (newBarrageItem != null) {
            addImageTextDanMu(newBarrageItem);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(BarrageListEvent event) {
        Logger.e("弹幕循环播放");
        showBarragesRandom(event.barrageList);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mVideoView.destroyVideo();
        mDanmuStuffer.clearCaches();
        mDanmakuView.release();
        mDanmakuView = null;
        //关闭线程池
        mExecutorService.shutdown();
        try {
            if (!mExecutorService.awaitTermination(2, TimeUnit.SECONDS)) {
                mExecutorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            mExecutorService.shutdownNow();
        }
    }

}
